home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 109 / EnigmaAmiga109CD.iso / dalla rivista / host contacted / jikes.lha / jikes-1.11 / src / bytecode.h < prev    next >
C/C++ Source or Header  |  1999-10-17  |  30KB  |  891 lines

  1. // $Id: bytecode.h,v 1.17 1999/10/17 01:58:39 shields Exp $
  2. //
  3. // License Agreement available at the following URL:
  4. // http://www.ibm.com/research/jikes.
  5. // Copyright (C) 1996, 1998, International Business Machines Corporation
  6. // and others.  All Rights Reserved.
  7. // You must accept the terms of that agreement to use this software.
  8.  
  9. //
  10. #ifndef bytecode_INCLUDED
  11. #define bytecode_INCLUDED
  12.  
  13. #include <stdio.h>
  14. #include "tuple.h"
  15. #include "ast.h"
  16. #include "class.h"
  17. #include "option.h"
  18. #include "long.h"
  19. #include "op.h"
  20. #include "segment.h"
  21.  
  22. class TypeSymbol;
  23. class Control;
  24. class Semantic;
  25.  
  26. class Label
  27. {
  28. public:
  29.  
  30.     class LabelUse
  31.     {
  32.     public:
  33.         int use_length, // length of use (2 or 4 bytes)
  34.             op_offset,  // length of use from opcode starting instruction
  35.             use_offset; // offset in code stream of use
  36.  
  37.         LabelUse() : use_length(0), op_offset(0), use_offset(0) {}
  38.  
  39.         LabelUse(int _length, int _op_offset, int _use) : use_length(_length), op_offset(_op_offset), use_offset(_use) {}
  40.     };
  41.  
  42.     bool defined;   // boolean, set when value is known
  43.     int definition; // offset of definition point of label
  44.     Tuple<LabelUse> uses;
  45.  
  46.     Label() : defined(false), definition(0) {}
  47.  
  48.     void Reset()
  49.     {
  50.        uses.Reset();
  51.        defined = false;
  52.        definition = 0;
  53.     }
  54. };
  55.  
  56.  
  57. //
  58. //
  59. //
  60. class MethodStack
  61. {
  62. public:
  63.  
  64.     void Push(AstBlock *block)
  65.     {
  66.         assert(block -> nesting_level < stack_size &&
  67.               (top_index == 0 || ((block -> nesting_level - 1) == nesting_level[top_index - 1])));
  68.  
  69.         nesting_level[top_index] = block -> nesting_level;
  70.         break_labels[block -> nesting_level].uses.Reset();
  71.         continue_labels[block -> nesting_level].uses.Reset();
  72.         finally_labels[block -> nesting_level].uses.Reset();
  73.         monitor_labels[block -> nesting_level].uses.Reset();
  74.         blocks[block -> nesting_level] = block;
  75.  
  76. #ifdef TEST
  77.         (void) memset(local_variables_start_pc[block -> nesting_level], 0xFF, size * sizeof(u2));
  78. #endif
  79.         top_index++;
  80.     }
  81.  
  82.     void Pop()
  83.     {
  84.         if (top_index > 0)
  85.         {
  86.             top_index--;
  87. #ifdef TEST
  88.             int level = nesting_level[top_index];
  89.  
  90.             nesting_level[top_index] = 0;
  91.             break_labels[level].Reset();
  92.             continue_labels[level].Reset();
  93.             finally_labels[level].Reset();
  94.             monitor_labels[level].Reset();
  95.             blocks[level] = NULL;
  96.             (void) memset(local_variables_start_pc[level], 0xFF, size * sizeof(u2));
  97. #endif
  98.         }
  99.         else assert(false);
  100.     }
  101.  
  102.     int Size() { return top_index; }
  103.  
  104. #ifdef TEST
  105.     void AssertIndex(int k)
  106.     {
  107.         for (int i = 0; i < Size(); i++)
  108.             if (nesting_level[i] == k)
  109.                 return;
  110.         assert(0);
  111.     }
  112. #else
  113. #define AssertIndex(x)
  114. #endif
  115.  
  116.     int TopNestingLevel()   { assert(top_index > 0); return nesting_level[top_index - 1]; }
  117.     int NestingLevel(int i) { AssertIndex(i); return nesting_level[i]; }
  118.  
  119.     Label &TopBreakLabel()    { return break_labels[TopNestingLevel()]; }
  120.     Label &BreakLabel(int i)  { AssertIndex(i); return break_labels[i]; }
  121.  
  122.     Label &TopContinueLabel()   { return continue_labels[TopNestingLevel()]; }
  123.     Label &ContinueLabel(int i) { AssertIndex(i); return continue_labels[i]; }
  124.  
  125.     Label &TopFinallyLabel()    { return finally_labels[TopNestingLevel()]; }
  126.     Label &FinallyLabel(int i)  { AssertIndex(i); return finally_labels[i]; }
  127.  
  128.     Label &TopMonitorLabel()   { return monitor_labels[TopNestingLevel()]; }
  129.     Label &MonitorLabel(int i) { AssertIndex(i); return monitor_labels[i]; }
  130.  
  131.     AstBlock *TopBlock()   { return blocks[TopNestingLevel()]; }
  132.     AstBlock *Block(int i) { AssertIndex(i); return blocks[i]; }
  133.  
  134.     //
  135.     //
  136.     //
  137.     u2 *TopLocalVariablesStartPc() { return (u2 *) local_variables_start_pc[TopNestingLevel()]; }
  138.     u2 &StartPc(VariableSymbol *variable)
  139.     {
  140.         assert(variable -> LocalVariableIndex() >= 0 && variable -> LocalVariableIndex() < size);
  141.         return TopLocalVariablesStartPc()[variable -> LocalVariableIndex()];
  142.     }
  143.  
  144.     MethodStack(int stack_size_, int size_) : stack_size(stack_size_),
  145.                                               size(size_),
  146.                                               top_index(0)
  147.     {
  148.         nesting_level = new int[stack_size];
  149.         break_labels = new Label[stack_size];
  150.         continue_labels = new Label[stack_size];
  151.         finally_labels = new Label[stack_size];
  152.         monitor_labels = new Label[stack_size];
  153.         blocks = new AstBlock *[stack_size];
  154.  
  155.         local_variables_start_pc = new u2*[stack_size];
  156.         for (int i = 0; i < stack_size; i++)
  157.             local_variables_start_pc[i] = new u2[size];
  158.     }
  159.     ~MethodStack()
  160.     {
  161.         delete [] nesting_level;
  162.  
  163.         delete [] break_labels;
  164.         delete [] continue_labels;
  165.         delete [] finally_labels;
  166.         delete [] monitor_labels;
  167.  
  168.         delete [] blocks;
  169.  
  170.         for (int i = 0; i < stack_size; i++)
  171.             delete [] local_variables_start_pc[i];
  172.         delete [] local_variables_start_pc;
  173.     }
  174.  
  175. private:
  176.     int *nesting_level;
  177.  
  178.     Label *break_labels,
  179.           *continue_labels,
  180.           *finally_labels,
  181.           *monitor_labels;
  182.  
  183.     AstBlock **blocks; // block symbols for current block
  184.  
  185.     u2 **local_variables_start_pc;
  186.     int stack_size,
  187.         size,
  188.         top_index;
  189. };
  190.  
  191.  
  192. class ByteCode : public ClassFile, public StringConstant, public Operators
  193. {
  194.     Control& this_control;
  195.     Semantic& this_semantic;
  196.  
  197.     void CompileClass();
  198.     void CompileInterface();
  199.  
  200.     int line_number,
  201.         last_label_pc,        // pc for last (closest to end) label
  202.         last_op_pc,           // pc of last operation emitted
  203.         last_op_nop,          // set if last operation was NOP.
  204.         stack_depth,          // current stack depth;
  205.         max_stack,
  206.         max_block_depth,
  207.         last_parameter_index; // set to local variable index of last parameter
  208.     MethodStack *method_stack;
  209.  
  210.     bool string_overflow,
  211.          library_method_not_found;
  212.  
  213.     Code_attribute *code_attribute; // code for current method ?
  214.     LineNumberTable_attribute *line_number_table_attribute;
  215.     LocalVariableTable_attribute *local_variable_table_attribute;
  216.     InnerClasses_attribute *inner_classes_attribute;
  217.  
  218.     void MethodInitialization()
  219.     {
  220.         last_label_pc = 0;
  221.         last_op_pc = 0;
  222.         last_op_nop = 0;
  223.  
  224.         stack_depth = 0;
  225.  
  226.         max_stack = 0;
  227.  
  228.         return;
  229.     }
  230.  
  231.     void    ProcessAbruptExit(int, TypeSymbol * = NULL);
  232.     void    CompleteLabel(Label &lab);
  233.     void    DefineLabel(Label &lab);
  234.     void    UseLabel(Label &lab, int length, int op_offset);
  235.  
  236.     bool IsLabelUsed(Label &lab)
  237.     {
  238.         return (lab.uses.Length() > 0);
  239.     }
  240.  
  241.  
  242.     //
  243.     // see if operand is null. The front-end will have inserted a cast
  244.     // of null to the present type
  245.     //
  246.     bool IsNull(AstExpression *p)
  247.     {
  248.         return (p -> CastExpressionCast() ? (p -> CastExpressionCast() -> expression -> Type() == this_control.null_type) : false);
  249.     }
  250.  
  251.  
  252.     //
  253.     // Does p refer to a non-null reference type?
  254.     //
  255.     bool IsReferenceType(TypeSymbol *p)
  256.     {
  257.         return (! (p -> Primitive() || p == this_control.null_type));
  258.     }
  259.  
  260.  
  261.     //
  262.     // see if operand is integer type and is zero
  263.     //
  264.     bool IsZero(AstExpression *p)
  265.     {
  266.         if (p -> IsConstant() && (p -> Type() == this_control.int_type || p -> Type() == this_control.boolean_type))
  267.         {
  268.             IntLiteralValue *vp = (IntLiteralValue *) (p -> value);
  269.             return (vp -> value == 0);
  270.         }
  271.  
  272.         return false;
  273.     }
  274.  
  275.  
  276.     //
  277.     // memory access: reference either
  278.     // constant (literal)
  279.     // name (includes local varable, or class variable, or field access)
  280.     // array
  281.     //
  282.     enum
  283.     {
  284.         LHS_LOCAL =  0, // local variable
  285.         LHS_ARRAY =  1, // array (of any kind)
  286.         LHS_FIELD =  2, // instance variable
  287.         LHS_STATIC = 3, // class variable
  288.         LHS_METHOD = 4 // access to private variable
  289.     };
  290.  
  291.     int GetLhsKind(AstExpression *expression)
  292.     {
  293.         AstAssignmentExpression *assignment = expression -> AssignmentExpressionCast();
  294.         AstPreUnaryExpression *pre = expression -> PreUnaryExpressionCast();
  295.         AstPostUnaryExpression *post = expression -> PostUnaryExpressionCast();
  296.  
  297.         AstExpression *lhs = assignment ? (assignment -> write_method ? (AstExpression *) NULL : assignment -> left_hand_side)
  298.                                         : pre ? (pre -> write_method ? (AstExpression *) NULL : pre -> expression)
  299.                                               : post ? (post -> write_method ? (AstExpression *) NULL : post -> expression)
  300.                                                      : expression;
  301.  
  302.         //
  303.         // Find symbol that is associated with expression. If the subexpression has
  304.         // to be referenced via an access method then the symbol is null
  305.         //
  306.         AstCastExpression *cast = (lhs ? lhs -> CastExpressionCast() : (AstCastExpression *) NULL);
  307.         Symbol *sym = cast ? cast -> expression -> symbol : (lhs ? lhs -> symbol : (Symbol *) NULL);
  308.  
  309.         //
  310.         // If the expression associated with the left-hand side is null,
  311.         // then we have an access method.
  312.         // Otherwise, a left-hand side is either an array access,
  313.         // a field access or a name. In the case of a FieldAccess
  314.         // or name, the left-hand side is resolved into a variable.
  315.         // In the case of an array access, it is resolved into a type.
  316.         //
  317.         VariableSymbol *var = (sym ? sym -> VariableCast() : (VariableSymbol *) NULL);
  318.         return ((! lhs) ? LHS_METHOD
  319.                         : (! var) ? LHS_ARRAY
  320.                                   : var -> owner -> MethodCast() ? LHS_LOCAL
  321.                                                                  : var -> ACC_STATIC() ? LHS_STATIC
  322.                                                                                        : LHS_FIELD);
  323.     }
  324.  
  325.  
  326.     int GetTypeWords(TypeSymbol *type)
  327.     {
  328.         return this_control.IsDoubleWordType(type) ? 2 : 1;
  329.     }
  330.  
  331.  
  332.     //
  333.     // methods to load and store values
  334.     //
  335.     void LoadLocal(int varno, TypeSymbol *);
  336.     void StoreLocal(int varno, TypeSymbol *);
  337.     void LoadReference(AstExpression *);
  338.     void LoadLiteral(LiteralValue *, TypeSymbol *);
  339.     void LoadImmediateInteger(int);
  340.     int  LoadVariable(int, AstExpression *);
  341.     int  LoadArrayElement(TypeSymbol *);
  342.     void StoreArrayElement(TypeSymbol *);
  343.     void StoreField(AstExpression *);
  344.     void StoreVariable(int, AstExpression *);
  345.  
  346.     void LoadConstantAtIndex(u2 index)
  347.     {
  348.         if (index <= 255)
  349.         {
  350.             PutOp(OP_LDC);
  351.             PutU1((u1) index);
  352.         }
  353.         else
  354.         {
  355.             PutOp(OP_LDC_W);
  356.             PutU2(index);
  357.         }
  358.  
  359.         return;
  360.     }
  361.  
  362.     //
  363.     // These pools are sets that keep track of elements that have
  364.     // already been inserted in the constant pool.
  365.     //
  366.     SegmentPool segment_pool;
  367.  
  368.     Pair *double_constant_pool_index,
  369.          *integer_constant_pool_index,
  370.          *long_constant_pool_index,
  371.          *float_constant_pool_index,
  372.          *string_constant_pool_index,
  373.  
  374.          utf8_constant_pool_index,
  375.          class_constant_pool_index;
  376.  
  377.     Triplet *name_and_type_constant_pool_index,
  378.             *fieldref_constant_pool_index,
  379.             *methodref_constant_pool_index;
  380.  
  381.     u2 RegisterNameAndType(Utf8LiteralValue *name, Utf8LiteralValue *type_name)
  382.     {
  383.         assert((name != NULL && type_name != NULL) && "null argument to RegisterNameAndType");
  384.  
  385.         if (! name_and_type_constant_pool_index)
  386.             name_and_type_constant_pool_index = new Triplet(segment_pool, this_control.Utf8_pool.symbol_pool.Length());
  387.  
  388.         u2 index = name_and_type_constant_pool_index -> Image(name -> index, type_name -> index);
  389.         if (index == 0)
  390.         {
  391.             int i = constant_pool.NextIndex(); // We cannot use the variable "index" here as it might be truncated
  392.             index = i;
  393.             name_and_type_constant_pool_index -> Image(name -> index, type_name -> index) = index;
  394.             constant_pool[i] = new CONSTANT_NameAndType_info(CONSTANT_NameAndType, RegisterUtf8(name), RegisterUtf8(type_name));
  395.         }
  396.  
  397.         return index;
  398.     }
  399.  
  400.  
  401.     u2 RegisterFieldref(Utf8LiteralValue *class_name,
  402.                         Utf8LiteralValue *field_name,
  403.                         Utf8LiteralValue *field_type_name)
  404.     {
  405.         assert((class_name != NULL && field_name != NULL && field_type_name != NULL) && "null argument to RegisterFieldref");
  406.  
  407.         if (! fieldref_constant_pool_index)
  408.             fieldref_constant_pool_index = new Triplet(segment_pool, this_control.Utf8_pool.symbol_pool.Length());
  409.  
  410.         u2 name_type_index = RegisterNameAndType(field_name, field_type_name),
  411.            index = fieldref_constant_pool_index -> Image(class_name -> index, name_type_index);
  412.         if (index == 0)
  413.         {
  414.             int i = constant_pool.NextIndex(); // We cannot use the variable "index" here as it might be truncated
  415.             index = i;
  416.             fieldref_constant_pool_index -> Image(class_name -> index, name_type_index) = index;
  417.             constant_pool[i] = new CONSTANT_Fieldref_info(CONSTANT_Fieldref, RegisterClass(class_name), name_type_index);
  418.         }
  419.  
  420.         return index;
  421.     }
  422.  
  423.  
  424.     u2 RegisterFieldref(TypeSymbol *type, VariableSymbol *variable_symbol)
  425.     {
  426.         assert(variable_symbol -> owner -> TypeCast());
  427.  
  428.         return RegisterFieldref(type -> fully_qualified_name,
  429.                                 variable_symbol -> ExternalIdentity() -> Utf8_literal,
  430.                                 variable_symbol -> Type() -> signature);
  431.     }
  432.  
  433.  
  434.     u2 RegisterFieldref(VariableSymbol *variable_symbol)
  435.     {
  436.         assert(variable_symbol -> owner -> TypeCast());
  437.  
  438.         return RegisterFieldref(variable_symbol -> owner -> TypeCast() -> fully_qualified_name,
  439.                                 variable_symbol -> ExternalIdentity() -> Utf8_literal,
  440.                                 variable_symbol -> Type() -> signature);
  441.     }
  442.  
  443.  
  444.     u2 RegisterMethodref(ConstantKind kind,
  445.                          Utf8LiteralValue *class_name,
  446.                          Utf8LiteralValue *method_name,
  447.                          Utf8LiteralValue *method_type_name)
  448.     {
  449.         assert((class_name != NULL && method_name != NULL && method_type_name != NULL) && "null argument to RegisterMethodref");
  450.  
  451.         if (! methodref_constant_pool_index)
  452.             methodref_constant_pool_index = new Triplet(segment_pool, this_control.Utf8_pool.symbol_pool.Length());
  453.  
  454.         u2 name_type_index = RegisterNameAndType(method_name, method_type_name),
  455.            index = methodref_constant_pool_index -> Image(class_name -> index, name_type_index);
  456.         if (index == 0)
  457.         {
  458.             int i = constant_pool.NextIndex(); // We cannot use the variable "index" here as it might be truncated
  459.             index = i;
  460.             methodref_constant_pool_index -> Image(class_name -> index, name_type_index) = index;
  461.  
  462.             u2 class_name_index = RegisterClass(class_name);
  463.             constant_pool[i] = (kind == CONSTANT_Methodref
  464.                                       ? (cp_info *) new CONSTANT_Methodref_info(CONSTANT_Methodref,
  465.                                                                                 class_name_index,
  466.                                                                                 name_type_index)
  467.                                       : (cp_info *) new CONSTANT_InterfaceMethodref_info(CONSTANT_InterfaceMethodref,
  468.                                                                                          class_name_index,
  469.                                                                                          name_type_index));
  470.         }
  471.  
  472.         return index;
  473.     }
  474.  
  475.  
  476.     u2 RegisterMethodref(Utf8LiteralValue *class_name, Utf8LiteralValue *method_name, Utf8LiteralValue *method_type_name)
  477.     {
  478.         return RegisterMethodref(CONSTANT_Methodref, class_name, method_name, method_type_name);
  479.     }
  480.  
  481.     u2 RegisterInterfaceMethodref(Utf8LiteralValue *class_name, Utf8LiteralValue *method_name, Utf8LiteralValue *method_type_name)
  482.     {
  483.         return RegisterMethodref(CONSTANT_InterfaceMethodref, class_name, method_name, method_type_name);
  484.     }
  485.  
  486.  
  487.     u2 RegisterLibraryMethodref(MethodSymbol *method)
  488.     {
  489.         if (method) // The library method must exist. If it is not, flag an error.
  490.             return RegisterMethodref(CONSTANT_Methodref, method -> containing_type -> fully_qualified_name,
  491.                                                          method -> ExternalIdentity()-> Utf8_literal,
  492.                                                          method -> signature);
  493.         library_method_not_found = true;
  494.  
  495.         return 0;
  496.     }
  497.  
  498.     u2 RegisterDouble(DoubleLiteralValue *lit)
  499.     {
  500.         assert((lit != NULL) && "null argument to RegisterDouble");
  501.  
  502.         if (! double_constant_pool_index)
  503.             double_constant_pool_index = new Pair(segment_pool, this_control.double_pool.symbol_pool.Length());
  504.  
  505.         u2 index = (*double_constant_pool_index)[lit -> index];
  506.         if (index == 0)
  507.         {
  508.             int i = constant_pool.NextIndex(); // We cannot use the variable "index" here as it might be truncated
  509.             constant_pool.Next() = NULL;       // extra slop for double-word entry
  510.             index = i;
  511.             (*double_constant_pool_index)[lit -> index] = index;
  512.             constant_pool[i] = new CONSTANT_Double_info(CONSTANT_Double, lit -> value.HighWord(), lit -> value.LowWord());
  513.         }
  514.  
  515.         return index;
  516.     }
  517.  
  518.  
  519.     u2 RegisterInteger(IntLiteralValue *lit)
  520.     {
  521.         assert((lit != NULL) && "null argument to RegisterInteger");
  522.  
  523.         if (! integer_constant_pool_index)
  524.             integer_constant_pool_index = new Pair(segment_pool, this_control.int_pool.symbol_pool.Length());
  525.  
  526.         u2 index = (*integer_constant_pool_index)[lit -> index];
  527.         if (index == 0)
  528.         {
  529.             int i = constant_pool.NextIndex(); // We cannot use the variable "index" here as it might be truncated
  530.             index = i;
  531.             (*integer_constant_pool_index)[lit -> index] = index;
  532.             int val = lit -> value;
  533.             u4 bytes = (((unsigned) (val >> 24)) << 24) | ((val >> 16 & 0xff) << 16) | ((val >> 8 & 0xff) ) << 8 | (val & 0xff);
  534.             constant_pool[i] = new CONSTANT_Integer_info(CONSTANT_Integer, bytes);
  535.         }
  536.  
  537.         return index;
  538.     }
  539.  
  540.  
  541.     u2 FindInteger(IntLiteralValue *lit)
  542.     {
  543.         return (lit && integer_constant_pool_index ? (*integer_constant_pool_index)[lit -> index] : 0);
  544.     }
  545.  
  546.  
  547.     u2 RegisterLong(LongLiteralValue *lit)
  548.     {
  549.         assert((lit != NULL) && "null argument to RegisterLong");
  550.  
  551.         if (! long_constant_pool_index)
  552.             long_constant_pool_index = new Pair(segment_pool, this_control.long_pool.symbol_pool.Length());
  553.  
  554.         u2 index = (*long_constant_pool_index)[lit -> index];
  555.         if (index == 0)
  556.         {
  557.             int i = constant_pool.NextIndex(); // We cannot use the variable "index" here as it might be truncated
  558.             constant_pool.Next() = NULL;       // extra slop for double-word entry
  559.             index = i;
  560.             (*long_constant_pool_index)[lit -> index] = index;
  561.             constant_pool[i] = new CONSTANT_Long_info(CONSTANT_Long, lit -> value.HighWord(), lit -> value.LowWord());
  562.         }
  563.  
  564.         return index;
  565.     }
  566.  
  567.  
  568.     u2 RegisterFloat(FloatLiteralValue *lit)
  569.     {
  570.         assert((lit != NULL) && "null argument to RegisterFloat");
  571.  
  572.         if (! float_constant_pool_index)
  573.             float_constant_pool_index = new Pair(segment_pool, this_control.float_pool.symbol_pool.Length());
  574.  
  575.         u2 index = (*float_constant_pool_index)[lit -> index];
  576.         if (index == 0)
  577.         {
  578.             int i = constant_pool.NextIndex(); // We cannot use the variable "index" here as it might be truncated
  579.             index = i;
  580.             (*float_constant_pool_index)[lit -> index] = index;
  581.             constant_pool[i] = new CONSTANT_Float_info(CONSTANT_Float, lit -> value.Word());
  582.         }
  583.  
  584.         return index;
  585.     }
  586.  
  587.  
  588.     u2 RegisterUtf8(Utf8LiteralValue *lit)
  589.     {
  590.         assert((lit != NULL) && "null argument to RegisterUtf8");
  591.  
  592.         u2 index = utf8_constant_pool_index[lit -> index];
  593.         if (index == 0)
  594.         {
  595.             int i = constant_pool.NextIndex(); // We cannot use the variable "index" here as it might be truncated
  596.             index = i;
  597.             utf8_constant_pool_index[lit -> index] = index;
  598.             constant_pool[i] = new CONSTANT_Utf8_info(CONSTANT_Utf8, lit -> value, lit -> length);
  599.         }
  600.  
  601.         return index;
  602.     }
  603.  
  604.  
  605.     u2 RegisterString(Utf8LiteralValue *lit)
  606.     {
  607.         assert((lit != NULL) && "null argument to RegisterString");
  608.  
  609.         //
  610.         // The domain of these maps is an index in the constant_pool.
  611.         // For a valid program, the size of the constant pool is limited
  612.         // to 65k elements.
  613.         //
  614.         if (! string_constant_pool_index)
  615.             string_constant_pool_index = new Pair(segment_pool, this_control.Utf8_pool.symbol_pool.Length());
  616.  
  617.         u2 index = (*string_constant_pool_index)[lit -> index];
  618.         if (index == 0)
  619.         {
  620.             int i = constant_pool.NextIndex(); // We cannot use the variable "index" here as it might be truncated
  621.             index = i;
  622.             (*string_constant_pool_index)[lit -> index] = index;
  623.             constant_pool[i] = new CONSTANT_String_info(CONSTANT_String, RegisterUtf8(lit));
  624.         }
  625.  
  626.         return index;
  627.     }
  628.  
  629.  
  630.     u2 RegisterClass(Utf8LiteralValue *lit)
  631.     {
  632.         assert((lit != NULL) && "null argument to RegisterClass");
  633.  
  634.         u2 index = class_constant_pool_index[lit -> index];
  635.         if (index == 0)
  636.         {
  637.             int i = constant_pool.NextIndex(); // We cannot use the variable "index" here as it might be truncated
  638.             index = i;
  639.             class_constant_pool_index[lit -> index] = index;
  640.             constant_pool[i] = new CONSTANT_Class_info(CONSTANT_Class, RegisterUtf8(lit));
  641.         }
  642.  
  643.         return index;
  644.     }
  645.  
  646.  
  647.     //
  648.     //  Methods to write out the byte code
  649.     //
  650.     Deprecated_attribute *CreateDeprecatedAttribute()
  651.     {
  652.         return new Deprecated_attribute(RegisterUtf8(this_control.Deprecated_literal));
  653.     }
  654.  
  655.  
  656.     Synthetic_attribute *CreateSyntheticAttribute()
  657.     {
  658.         return new Synthetic_attribute(RegisterUtf8(this_control.Synthetic_literal));
  659.     }
  660.  
  661.  
  662.     //
  663.     // Methods to generate expressions.
  664.     //
  665.     int  EmitExpression(AstExpression *);
  666.     int  EmitArrayCreationExpression(AstArrayCreationExpression *);
  667.     int  EmitAssignmentExpression(AstAssignmentExpression *, bool);
  668.     int  EmitBinaryExpression(AstBinaryExpression *);
  669.     int  EmitCastExpression(AstCastExpression *);
  670.     void EmitCast(TypeSymbol *, TypeSymbol *);
  671.     int  EmitClassInstanceCreationExpression(AstClassInstanceCreationExpression *, bool);
  672.     int  EmitConditionalExpression(AstConditionalExpression *);
  673.     int  EmitFieldAccess(AstFieldAccess *);
  674.     AstExpression *VariableExpressionResolution(AstExpression *);
  675.     TypeSymbol *VariableTypeResolution(AstExpression *, VariableSymbol *);
  676.     TypeSymbol *MethodTypeResolution(AstExpression *, MethodSymbol *);
  677.     void EmitFieldAccessLhsBase(AstExpression *);
  678.     void EmitFieldAccessLhs(AstExpression *);
  679.     void EmitMethodInvocation(AstMethodInvocation *);
  680.     void EmitNewArray(int, TypeSymbol *);
  681.     int  EmitPostUnaryExpression(AstPostUnaryExpression *, bool);
  682.     void EmitPostUnaryExpressionArray(AstPostUnaryExpression *, bool);
  683.     void EmitPostUnaryExpressionField(int, AstPostUnaryExpression *, bool);
  684.     void EmitPostUnaryExpressionSimple(int, AstPostUnaryExpression *, bool);
  685.     int  EmitPreUnaryExpression(AstPreUnaryExpression *, bool);
  686.     void EmitPreUnaryIncrementExpression(AstPreUnaryExpression *expression, bool);
  687.     void EmitPreUnaryIncrementExpressionArray(AstPreUnaryExpression *expression, bool);
  688.     void EmitPreUnaryIncrementExpressionField(int, AstPreUnaryExpression *expression, bool);
  689.     void EmitPreUnaryIncrementExpressionSimple(int, AstPreUnaryExpression *expression, bool);
  690.     void EmitThisInvocation(AstThisCall *);
  691.     void EmitSuperInvocation(AstSuperCall *);
  692.     void ConcatenateString(AstBinaryExpression *);
  693.     void AppendString(AstExpression *);
  694.     void EmitStringAppendMethod(TypeSymbol *);
  695.     void GenerateAccessMethod(MethodSymbol *);
  696.     void ChangeStack (int);
  697.     void ResolveAccess(AstExpression *);
  698.     int  GenerateClassAccess(AstFieldAccess *);
  699.     void GenerateClassAccessMethod(MethodSymbol *);
  700.  
  701.     //
  702.     // Methods to process statements
  703.     //
  704.     void CompileConstructor(AstConstructorDeclaration *, Tuple<AstVariableDeclarator *> &);
  705.  
  706.     void BeginMethod(int, MethodSymbol *);
  707.     void EndMethod(int, MethodSymbol *);
  708.     void DeclareField(VariableSymbol *);
  709.     void InitializeClassVariable(AstVariableDeclarator *);
  710.     void InitializeInstanceVariable(AstVariableDeclarator *);
  711.     void InitializeArray(TypeSymbol *, AstArrayInitializer *);
  712.     void DeclareLocalVariable(AstVariableDeclarator *);
  713.     void EmitStatement(AstStatement *);
  714.     void EmitReturnStatement(AstReturnStatement *);
  715.     void EmitSynchronizedStatement(AstSynchronizedStatement *);
  716.     void EmitBlockStatement(AstBlock *);
  717.     void EmitStatementExpression(AstExpression *);
  718.     void EmitSwitchStatement(AstSwitchStatement *);
  719.     void EmitTryStatement(AstTryStatement *);
  720.     void EmitBranchIfExpression(AstExpression *, bool, Label &);
  721.     void CompleteCall(MethodSymbol *, int, TypeSymbol * = NULL);
  722.  
  723.  
  724.     //
  725.     // called when expression has been parenthesized to removed
  726.     // parantheses and expose true structure.
  727.     //
  728.     AstExpression *UnParenthesize(AstExpression *expr)
  729.     {
  730.         while(expr -> ParenthesizedExpressionCast())
  731.             expr = expr -> ParenthesizedExpressionCast() -> expression;
  732.  
  733.         return expr;
  734.     }
  735.  
  736.  
  737.     void EmitArrayAccessLhs(AstArrayAccess *expression)
  738.     {
  739.         LoadReference(expression -> base);
  740.         EmitExpression(expression -> expression);
  741.  
  742.         return;
  743.     }
  744.  
  745.  
  746.     int EmitArrayAccessRhs(AstArrayAccess *expression)
  747.     {
  748.         EmitArrayAccessLhs(expression); // get array address and index
  749.         return LoadArrayElement(expression -> Type());
  750.     }
  751.  
  752.  
  753.     void EmitBranch(unsigned int opc, Label& lab)
  754.     {
  755.         PutOp(opc);
  756.         UseLabel(lab, 2, 1);
  757.  
  758.         return;
  759.     }
  760.  
  761.  
  762.     void GenerateReturn(TypeSymbol *type)
  763.     {
  764.         PutOp(this_control.IsSimpleIntegerValueType(type) || type == this_control.boolean_type
  765.                   ? OP_IRETURN
  766.                   : type == this_control.long_type
  767.                           ? OP_LRETURN
  768.                           : type == this_control.float_type
  769.                                   ? OP_FRETURN
  770.                                   : type == this_control.double_type
  771.                                           ? OP_DRETURN
  772.                                           : OP_ARETURN);
  773.         return;
  774.     }
  775.  
  776.  
  777. #ifdef TEST
  778.     void PrintCode();
  779. #endif
  780.  
  781.     void PutOp(unsigned char opc);
  782.  
  783.     void PutOpWide(unsigned char opc, u2 var);
  784.  
  785.     void PutOpIINC(u2 var, int val);
  786.  
  787.     //
  788.     //  Methods to insert values into byte code
  789.     //
  790.     void PutI1(i1 i)
  791.     {
  792.         code_attribute -> AddCode(i & 0xff);
  793.  
  794.         return;
  795.     }
  796.  
  797.  
  798.     void PutI2(i2 i)
  799.     {
  800.         code_attribute -> AddCode((i >> 8) & 0xff);
  801.         code_attribute -> AddCode(i & 0xff);
  802.  
  803.         return;
  804.     }
  805.  
  806.  
  807.     void PutU1(u1 u)
  808.     {
  809.         code_attribute -> AddCode(u & 0xff);
  810.  
  811.         return;
  812.     }
  813.  
  814.  
  815.     void PutU2(u2 u)
  816.     {
  817.         code_attribute -> AddCode((u >> 8) & 0xff);
  818.         code_attribute -> AddCode(u & 0xff);
  819.  
  820.         return;
  821.     }
  822.  
  823.  
  824.     void PutU4(u4 u)
  825.     {
  826.         code_attribute -> AddCode((u >> 24));
  827.         code_attribute -> AddCode((u >> 16) & 0xff);
  828.         code_attribute -> AddCode((u >>  8) & 0xff);
  829.         code_attribute -> AddCode(u & 0xff);
  830.  
  831.         return;
  832.     }
  833.  
  834.  
  835.     //
  836.     // emit NOP. The NOP can be replaced by the next instruction if
  837.     // optional is set; otherwise it must be kept.
  838.     //
  839.     void PutNop(int optional)
  840.     {
  841.         PutOp(OP_NOP);
  842.  
  843.         //
  844.         // this optimization is causing more trouble than it's worth.
  845.         // latest problem (27 jan 97) was reported by Derek, in that
  846.         // nop just before label definition, resulted in operation generated
  847.         // after label def. being moved before the def! Since it's such a sin
  848.         // to generate junk code, disable the "nop" optimization.
  849.         //  if (optional) last_op_nop = 1;
  850.         //
  851.  
  852.         return;
  853.     }
  854.  
  855.     void FinishCode(TypeSymbol *);
  856.  
  857.     void Reset()
  858.     {
  859.         constant_pool.Reset();
  860.         fields.Reset();
  861.         methods.Reset();
  862.         attributes.Reset();
  863.         this_class = super_class = 0;
  864.     }
  865.  
  866. public:
  867.     ByteCode(TypeSymbol *);
  868.  
  869.     ~ByteCode()
  870.     {
  871.         delete double_constant_pool_index;
  872.         delete integer_constant_pool_index;
  873.         delete long_constant_pool_index;
  874.         delete float_constant_pool_index;
  875.         delete string_constant_pool_index;
  876.  
  877.         delete name_and_type_constant_pool_index;
  878.         delete fieldref_constant_pool_index;
  879.         delete methodref_constant_pool_index;
  880.     }
  881.  
  882.     inline void GenerateCode()
  883.     {
  884.         if (unit_type -> ACC_INTERFACE())
  885.              CompileInterface();
  886.         else CompileClass();
  887.     }
  888. };
  889.  
  890. #endif
  891.